﻿
#region Copyright & License
// --------------------------
// Copyright 2008 Daniel Gray
// --------------------------
// This file is part of Kale.
//
// Kale is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Kale is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Kale.  If not, see <http://www.gnu.org/licenses/>.
#endregion
#region File details
// --------------------------------------------------------
// Filename          : NodeId.cs
// Author            : Daniel Gray
// Created           : 15/04/2008
// --------------------------------------------------------
#endregion
            
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Kale.Core
{
   /// <summary>
   /// Provides the structure for identifying a node.
   /// </summary>
   public struct NodeId
   {
      private readonly NodeSource _source;
      private readonly string _store;
      private readonly string _path;

      /// <summary>
      /// Initializes a new instance of the <see cref="NodeId"/> struct.
      /// </summary>
      /// <param name="source">The source.</param>
      /// <param name="topItem">The top item.</param>
      /// <param name="path">The path.</param>
      public NodeId(NodeSource source, string store, string path)
      {
         _source = source;
         _store = store;
         _path = path;
      }

      /// <summary>
      /// Gets the source part of the ID.
      /// </summary>
      /// <value>The source.</value>
      public NodeSource Source
      {
         get { return _source; }
      }

      /// <summary>
      /// Gets the top item part of the ID.
      /// </summary>
      /// <value>The top item.</value>
      public string Store
      {
         get { return _store; }
      }

      /// <summary>
      /// Gets the path part of the ID.
      /// </summary>
      /// <value>The path.</value>
      public string Path
      {
         get { return _path; }
      }

      /// <summary>
      /// Returns the fully qualified type name of this instance.
      /// </summary>
      /// <returns>
      /// A <see cref="T:System.String"/> containing a fully qualified type name.
      /// </returns>
      public override string ToString()
      {
         if (!string.IsNullOrEmpty(Store) && !string.IsNullOrEmpty(Path))
         {
            return string.Format("{0}:{1}:{2}", Source, Store, Path);
         }
         else if (!string.IsNullOrEmpty(Store))
         {
            return string.Format("{0}:{1}", Source, Store);
         }
         else
         {
            return Source.ToString();
         }
      }

      /// <summary>
      /// Gets the cache key for this node id for a specified size.
      /// </summary>
      /// <param name="size">The size.</param>
      /// <returns></returns>
      public string GetCacheKey(Size size)
      {
         return string.Format("{0}_{1}_{2}", size.Width, size.Height, GetCacheKey());
      }

      /// <summary>
      /// Gets the cache key for this node id.
      /// </summary>
      /// <returns></returns>
      public string GetCacheKey()
      {
         return ToString().Replace(':', '_').Replace('\\','_');
      }

      /// <summary>
      /// Parses a NoewId from an id string.
      /// </summary>
      /// <param name="id">The id string.</param>
      /// <returns></returns>
      public static NodeId ParseFromIdString(string id)
      {
         string[] parts = id.Split(':');

         if (parts.Length < 1 || parts.Length > 3) throw new FormatException("Invalid NodeId format");

         NodeSource source = NodeSource.Album;

         switch (parts[0])
         {
            case "Album" :
               source = NodeSource.Album;
               break;
            case "Disk" :
               source = NodeSource.Disk;
               break;
            case "Root" :
               source = NodeSource.Root;
               break;
            default:
               throw new FormatException(string.Format("Invalid node source {0}", parts[0]));
               break;
         }

         string topItem = string.Empty;
         string path = string.Empty;

         if (parts.Length == 2) topItem = parts[1];
         if (parts.Length == 3)
         {
            topItem = parts[1];
            path = parts[2];
         }

         return new NodeId(source, topItem, path);
      }

      /// <summary>
      /// Indicates whether this instance and a specified object are equal.
      /// </summary>
      /// <param name="obj">Another object to compare to.</param>
      /// <returns>
      /// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
      /// </returns>
      public override bool Equals(object obj)
      {
         if (obj == null) return false;

         if (this.GetType() != obj.GetType()) return false;

         // safe because of the GetType check
         NodeId id = (NodeId)obj;

         // use this pattern to compare value members
         if (!Source.Equals(id.Source)) return false;
         if (!Store.Equals(id.Store)) return false;
         if (!Path.Equals(id.Path)) return false;

         return true;
      }

      /// <summary>
      /// Implements the operator ==.
      /// </summary>
      /// <param name="a">A.</param>
      /// <param name="b">The b.</param>
      /// <returns>The result of the operator.</returns>
      public static bool operator ==(NodeId a, NodeId b)
      {

         // Return true if the fields match:
         return a.Source == b.Source && a.Store == b.Store && a.Path == b.Path;
      }

      /// <summary>
      /// Implements the operator !=.
      /// </summary>
      /// <param name="a">A.</param>
      /// <param name="b">The b.</param>
      /// <returns>The result of the operator.</returns>
      public static bool operator !=(NodeId a, NodeId b)
      {
         return !(a == b);
      }
   }
}
